package com.witframework.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import com.witframework.WitException;
import com.witframework.exception.WitIOException;
import com.witframework.security.DecryptFile;


/**
 * 
 * @author wuxinyang
 * Apr 9, 2009 11:56:32 AM
 *
 */
public class ApplicationProperties {
	
	private static Properties properties;	
	static int call=0;
	static{		
		new ApplicationProperties();
	}	
	
	private  ApplicationProperties() {
		
		try {		
			properties=loadAllProperties("config/application.dec.properties",null,false);	
			if(properties==null||properties.keySet().size()==0)
				properties=loadAllProperties("config/application.properties",null,true);				
		} catch (IOException e) {			
			throw new WitIOException("application.properties",e);
		}
		Properties properties2=null;
		try {
			properties2=loadAllProperties("application.properties",null,false);
		} catch (Exception e) {	}	
		if(properties2!=null){
			Iterator<Object> ikey=properties2.keySet().iterator();
			while(ikey.hasNext()){
				String key=(String)ikey.next();
				String v=properties2.getProperty(key);
				if(v!=null&&!key.equals("serial")){
					//允许追加属性
					if(key.equals("hibernate.cache.class")||
						key.equals("application.initializer")||
						key.equals("security.guest")){
						String v1=properties.getProperty(key);
						if(StringUtils.isNotEmpty(v1))
							v=v1+","+v;
					}
					properties.setProperty(key,v);
					
				}
			}
		}
		SerialChecker.check();		
	}
	public static Properties getProperties(){
		return properties;
	}
	public static String getProperty(String key){		
		String value= properties.getProperty(key);
		String EL;
		while((EL=findEL(value))!=null){
			String elValue= properties.getProperty(EL.substring(2,EL.length()-1));
			value=value.replace(EL,elValue);
		}
		return value;
	}
	public static int getPropertyIntValue(String key){		
		return Integer.parseInt(getProperty(key));
	}
	public static long getPropertyLongValue(String key){		
		return Long.parseLong(getProperty(key));
	}
	
	private static String findEL(String value) {	
		if(value!=null){
			Pattern p = Pattern.compile("\\${1}\\{{1}[^\\{\\}]+\\}{1}");
			Matcher m = p.matcher(value);
			if (m.find()) {
				return m.group().trim();
			}
		}
		return null;
	}	
	public static String getProperty(String key,String defaultValue){		
		return properties.getProperty(key, defaultValue);
	}
	public static void setProperty(String key,String value){
		properties.setProperty(key, value);		
	}
	public static void reload(){
		new ApplicationProperties();
	}
	public static Properties loadAllProperties(String resourceName, ClassLoader classLoader,boolean isEncrypt) throws IOException {
		Assert.notNull(resourceName, "Resource name must not be null");
		
		ClassLoader clToUse = classLoader;
		if (clToUse == null) {
			clToUse = ClassUtils.getDefaultClassLoader();
		}
		Properties properties = new Properties();
		Enumeration urls = clToUse.getResources(resourceName);
		while (urls.hasMoreElements()) {
			URL url = (URL) urls.nextElement();
			InputStream is = null;
			try {
				URLConnection con = url.openConnection();
				con.setUseCaches(false);
				is = con.getInputStream();
				if(isEncrypt)
					is=DecryptFile.decrypt(clToUse.getResourceAsStream("config/keyFile"), is);
				properties.load(is);
			}catch(Exception e){
				throw new WitException("decrypt file error",e);
			}
			finally {
				if (is != null) {
					is.close();
				}
			}
		}
		return properties;
	}
	public static int getCall() {
		return call;
	}
}
